#include "lpfconfig.h"
#include "dmdef.h"

namespace LpfConfig {

namespace BesselFilter {

BiquadCoeffs calculateCoeffs(double cutoffFreq, Slope slope)
{
    BiquadCoeffs coeffs;

    const BesselParam* param = nullptr;
    for (const auto& p : LPF_BESSEL) {
        if (p.scale == 0.0) continue;
        if (p.slope == slope) {
            param = &p;
            break;
        }
    }
    if (!param) return coeffs;

    const double scaledCutoff = cutoffFreq / param->scale;
    const double w0 = scaledCutoff * FilterConfig::FS_PI;
    const double alpha1 = tan(w0 / 2.0);
    const double alpha2 = alpha1 * alpha1;

    for (size_t i = 0; i < COEFFS_SIZE; ++i) {
        const double qa = param->Qa[i];
        const double qb = param->Qb[i];

        if (fabs(qa) < EPSILON_12E) {
            coeffs.a0[i] = 1.0;
            coeffs.a1[i] = 0.0;
            coeffs.a2[i] = 0.0;
            coeffs.b0[i] = 1.0;
            coeffs.b1[i] = 0.0;
            coeffs.b2[i] = 0.0;
        } else {
            coeffs.a0[i] = alpha2 + qa * alpha1 + qb;
            coeffs.a1[i] = 2 * (alpha2 - qb);
            coeffs.a2[i] = alpha2 - qa * alpha1 + qb;
            coeffs.b0[i] = alpha2;
            coeffs.b1[i] = 2 * alpha2;
            coeffs.b2[i] = alpha2;

            if (fabs(coeffs.a0[i]) < EPSILON_12E) {
                coeffs.a0[i] = EPSILON_10E;
            }
        }
    }

    return coeffs;
}

}

BiquadCoeffs LrButterFilter::calculateCoeffs(double cutoffFreq, PfType type, Slope slope)
{
    BiquadCoeffs coeffs;

    const LrButterParam* param = nullptr;
    if (PfType::ButterWorth == type) {
        for (const auto& p : LPF_BUTTER_WORTH) {
            if (p.slope == slope) {
                param = &p;
                break;
            }
        }
    }
    else if (PfType::LinkwitzRiley == type) {
        for (const auto& p : LPF_LINKWITZ_RILEY) {
            if (p.slope == slope) {
                param = &p;
                break;
            }
        }
    }

    if (!param) return coeffs; // 错误处理

    const double w0 = cutoffFreq * FilterConfig::FS_PI;
    const double w0_cValue = cos(w0);
    const double w0_sValue = sin(w0);
    // const double w_l = w0 * 0.5;
    // const double alph_l = tan(w_l);

    for (size_t i = 0; i < COEFFS_SIZE; ++i) {
        const double q = param->q[i];

        if (fabs(q) < EPSILON_12E) {
            coeffs.a0[i] = 1.0;
            coeffs.a1[i] = 0.0;
            coeffs.a2[i] = 0.0;
            coeffs.b0[i] = 1.0;
            coeffs.b1[i] = 0.0;
            coeffs.b2[i] = 0.0;
        } else {
            const double alpha = w0_sValue * q;

            coeffs.a0[i] = 1.0 + alpha;
            coeffs.a1[i] = -2.0 * w0_cValue;
            coeffs.a2[i] = 1.0 - alpha;
            coeffs.b0[i] = (1.0 - w0_cValue) / 2.0;
            coeffs.b1[i] = 2.0 * coeffs.b0[i];
            coeffs.b2[i] = coeffs.b0[i];

            // if ((slope == Slope::Oct_18dB || slope == Slope::Oct_30dB || slope == Slope::Oct_42dB) && i == 0) {
            //     coeffs.a0[i] = alph_l + q;
            //     coeffs.a1[i] = alph_l - q;
            //     coeffs.a2[i] = 0.0;
            //     coeffs.b0[i] = alph_l;
            //     coeffs.b1[i] = alph_l;
            //     coeffs.b2[i] = 0.0;
            // }

            if (fabs(coeffs.a0[i]) < EPSILON_12E) {
                coeffs.a0[i] = EPSILON_10E;
            }
        }
    }

    return coeffs;
}


}
